package com.vm.utils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;

import com.vm.db.DownInfoDao;
import com.vm.model.DownInfo;

import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class Downloader {

	private static final String TAG = "Downloader";
	private int done;
	private DownInfoDao dao;
	private int fileLen;
	private Handler handler;
	private boolean isPause;

	public Downloader(Context context, Handler handler) {
		dao = new DownInfoDao(context);
		this.handler = handler;
	}

	/**
	 * 多线程下载
	 * 
	 * @param path
	 *            下载路径
	 * @param thCount
	 *            需要开启多少个线程
	 * @throws Exception
	 */
	public void download(String path, int thCount) throws Exception {
		URL url = new URL(path);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		// 设置超时时间
		// conn.setConnectTimeout(3000);
		try {
			if (conn.getResponseCode() == 200) {
				fileLen = conn.getContentLength();
				String fileName = path.substring(path.lastIndexOf("/") + 1);

				String decodeString = URLDecoder.decode(fileName, "UTF-8");
				String lastFilename = decodeString.substring(19);
				String filename = lastFilename + ".apk";
				File file = new File(Environment.getExternalStorageDirectory()
						.getPath() + "/vmclient/" + filename);
				try {
					RandomAccessFile raf = new RandomAccessFile(file, "rws");
					raf.setLength(fileLen);
					raf.close();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					Log.e(TAG, e.getMessage());
				}

				// Handler发送消息，主线程接收消息，获取数据的长度
				Message msg = new Message();
				msg.what = 0;
				msg.getData().putInt("fileLen", fileLen);
				handler.sendMessage(msg);

				// 计算每个线程下载的字节数
				// int partLen = (fileLen + thCount - 1) / thCount;
				String threadId = lastFilename;
				new DownloadThread(url, file, fileLen, threadId).start();
			} else {
				throw new IllegalArgumentException("404 path: " + path);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			Log.e(TAG, e.getMessage());
		}
	}

	private final class DownloadThread extends Thread {
		private URL url;
		private File file;
		private int fileLen;
		private String softId;

		public DownloadThread(URL url, File file, int fileLen, String threadId) {
			this.url = url;
			this.file = file;
			this.fileLen = fileLen;
			this.softId = threadId;
		}

		/**
		 * 写入操作
		 */
		public void run() {
			// 判断上次是否有未完成任务
			DownInfo info = dao.query(softId);

			if (info != null) {
				// 如果有, 读取当前线程已下载量
				done += info.getDone();
				isPause = info.getIsPause() == 0 ? false : true;
			} else {
				// 如果没有, 则创建一个新记录存入
				info = new DownInfo();
				info.setPath(url.toString());
				info.setSoftId(softId);
				info.setIsPause(0);
				info.setDone(0);
				info.setApkLength(fileLen);
				dao.insert(info);
			}

			int start = info.getDone(); // 开始位置 += 已下载量
			int end = info.getApkLength();

			try {
				HttpURLConnection conn = (HttpURLConnection) url
						.openConnection();
				conn.setReadTimeout(3000);
				// 获取指定位置的数据，Range范围如果超出服务器上数据范围, 会以服务器数据末尾为准
				conn.setRequestProperty("Range", "bytes=" + start + "-" + end);
				RandomAccessFile raf = new RandomAccessFile(file, "rws");
				raf.seek(start);
				// 开始读写数据
				InputStream in = conn.getInputStream();
				byte[] buf = new byte[1024 * 10];
				int len;
				while ((len = in.read(buf)) != -1) {
					if (isPause) {
						// 使用线程锁锁定该线程
						synchronized (dao) {
							try {
								dao.wait();
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
					}
					raf.write(buf, 0, len);
					done += len;
					info.setDone(info.getDone() + len);
					// 记录每个线程已下载的数据量
					dao.update(info);
					// 新线程中用Handler发送消息，主线程接收消息
					Message msg = new Message();
					msg.what = 1;
					msg.getData().putInt("done", done);

					Log.i(TAG, "start="+start+",end="+end+",done="+done);
//					if (start >= end) {
//						// 删除下载记录
//						dao.delete(info.getPath(), threadId);
//
//						in.close();
//						raf.close();
//						conn.disconnect();
//					}
					handler.sendMessage(msg);

				}

			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

	// 暂停下载
	public void pause() {
		isPause = true;
		DownInfo info = dao.query("00828565-9986-46c6-b097-63a077cedf18");
		info.setIsPause(1);
		dao.update(info);

	}

	// 继续下载
	public void resume() {
		isPause = false;
		DownInfo info = dao.query("00828565-9986-46c6-b097-63a077cedf18");
		info.setIsPause(0);
		dao.update(info);

		// 恢复所有线程
		synchronized (dao) {
			dao.notifyAll();
		}
	}
}